/*
 * @Author: lixu lixu@puchigames.com
 * @Date: 2025-09-17 18:45:00
 * @LastEditors: lixu lixu@puchigames.com
 * @LastEditTime: 2025-09-18 10:04:25
 * @FilePath: /go-helper/utils/string.go
 * @Description: 字符串处理工具函数，包含字符串格式化、命名转换等功能
 */

package ixUtils

import (
	"net"
	"net/url"
	"regexp"
	"strings"
	"unicode"
)

// PadLeft 在字符串左侧填充指定字符到指定长度
func PadLeft(str string, length int, pad string) string {
	if len(str) >= length {
		return str
	}

	if pad == "" {
		pad = " "
	}

	padLength := length - len(str)
	padding := strings.Repeat(pad, (padLength/len(pad))+1)
	padding = padding[:padLength]

	return padding + str
}

// PadRight 在字符串右侧填充指定字符到指定长度
func PadRight(str string, length int, pad string) string {
	if len(str) >= length {
		return str
	}

	if pad == "" {
		pad = " "
	}

	padLength := length - len(str)
	padding := strings.Repeat(pad, (padLength/len(pad))+1)
	padding = padding[:padLength]

	return str + padding
}

// Truncate 截断字符串到指定长度，超出部分用后缀替代
func Truncate(str string, length int, suffix string) string {
	if len(str) <= length {
		return str
	}

	if suffix == "" {
		suffix = "..."
	}

	if length <= len(suffix) {
		return suffix[:length]
	}

	return str[:length-len(suffix)] + suffix
}

// Capitalize 将字符串首字母大写
func Capitalize(str string) string {
	if str == "" {
		return str
	}

	runes := []rune(str)
	runes[0] = unicode.ToUpper(runes[0])

	// 其余字母转小写
	for i := 1; i < len(runes); i++ {
		runes[i] = unicode.ToLower(runes[i])
	}

	return string(runes)
}

// CamelCase 转换为驼峰命名（首字母小写）
func CamelCase(str string) string {
	if str == "" {
		return str
	}

	// 分割字符串
	words := splitWords(str)
	if len(words) == 0 {
		return str
	}

	// 第一个单词小写，其余单词首字母大写
	result := strings.ToLower(words[0])
	for i := 1; i < len(words); i++ {
		if words[i] != "" {
			result += Capitalize(words[i])
		}
	}

	return result
}

// SnakeCase 转换为蛇形命名（下划线分隔）
func SnakeCase(str string) string {
	if str == "" {
		return str
	}

	// 处理驼峰命名
	var result []rune
	runes := []rune(str)

	for i, r := range runes {
		if i > 0 && unicode.IsUpper(r) {
			// 在大写字母前添加下划线
			result = append(result, '_')
		}
		result = append(result, unicode.ToLower(r))
	}

	resultStr := string(result)

	// 处理特殊字符，替换为下划线
	resultStr = strings.ReplaceAll(resultStr, " ", "_")
	resultStr = strings.ReplaceAll(resultStr, "-", "_")
	resultStr = strings.ReplaceAll(resultStr, ".", "_")

	// 移除连续的下划线
	for strings.Contains(resultStr, "__") {
		resultStr = strings.ReplaceAll(resultStr, "__", "_")
	}

	// 移除首尾下划线
	resultStr = strings.Trim(resultStr, "_")

	return resultStr
}

// KebabCase 转换为短横线命名（连字符分隔）
func KebabCase(str string) string {
	if str == "" {
		return str
	}

	// 先转换为蛇形命名，然后替换下划线为短横线
	snakeStr := SnakeCase(str)
	return strings.ReplaceAll(snakeStr, "_", "-")
}

// splitWords 分割单词（内部辅助函数）
func splitWords(str string) []string {
	// 替换常见分隔符为空格
	str = strings.ReplaceAll(str, "_", " ")
	str = strings.ReplaceAll(str, "-", " ")
	str = strings.ReplaceAll(str, ".", " ")

	// 处理驼峰命名
	var result []rune
	runes := []rune(str)

	for i, r := range runes {
		if i > 0 && unicode.IsUpper(r) && unicode.IsLower(runes[i-1]) {
			result = append(result, ' ')
		}
		result = append(result, r)
	}

	// 分割并过滤空字符串
	words := strings.Fields(string(result))
	var filteredWords []string
	for _, word := range words {
		if word != "" {
			filteredWords = append(filteredWords, word)
		}
	}

	return filteredWords
}

// ========== 字符串检查函数 ==========

// IsBlank 检查字符串是否为空白（空或只包含空白字符）
func IsBlank(str string) bool {
	return strings.TrimSpace(str) == ""
}

// IsNotEmpty 检查字符串是否不为空
func IsNotEmpty(str string) bool {
	return str != ""
}

// IsNotBlank 检查字符串是否不为空白
func IsNotBlank(str string) bool {
	return strings.TrimSpace(str) != ""
}

// ========== 字符串清理函数 ==========

// Trim 去除字符串前后空白字符
func Trim(str string) string {
	return strings.TrimSpace(str)
}

// TrimLeft 去除字符串左侧指定字符
func TrimLeft(str, cutset string) string {
	return strings.TrimLeft(str, cutset)
}

// TrimRight 去除字符串右侧指定字符
func TrimRight(str, cutset string) string {
	return strings.TrimRight(str, cutset)
}

// ========== 字符串操作函数 ==========

// ReverseString 反转字符串
func ReverseString(str string) string {
	runes := []rune(str)
	for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
		runes[i], runes[j] = runes[j], runes[i]
	}
	return string(runes)
}

// Repeat 重复字符串指定次数
func Repeat(str string, count int) string {
	if count <= 0 {
		return ""
	}
	return strings.Repeat(str, count)
}

// ========== 字符串格式化增强函数 ==========

// PascalCase 转换为帕斯卡命名（首字母大写的驼峰）
func PascalCase(str string) string {
	if str == "" {
		return str
	}

	words := splitWords(str)
	if len(words) == 0 {
		return str
	}

	var result string
	for _, word := range words {
		if word != "" {
			result += Capitalize(word)
		}
	}

	return result
}

// TitleCase 转换为标题格式（每个单词首字母大写）
func TitleCase(str string) string {
	if str == "" {
		return str
	}

	words := splitWords(str)
	if len(words) == 0 {
		return str
	}

	var result []string
	for _, word := range words {
		if word != "" {
			result = append(result, Capitalize(word))
		}
	}

	return strings.Join(result, " ")
}

// LowerCase 转换为小写
func LowerCase(str string) string {
	return strings.ToLower(str)
}

// UpperCase 转换为大写
func UpperCase(str string) string {
	return strings.ToUpper(str)
}

// ========== 字符串验证函数 ==========

// IsEmail 验证邮箱格式
func IsEmail(str string) bool {
	if str == "" {
		return false
	}

	// 邮箱正则表达式
	emailRegex := regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
	return emailRegex.MatchString(str)
}

// IsPhone 验证手机号格式（支持中国大陆手机号）
func IsPhone(str string) bool {
	if str == "" {
		return false
	}

	// 中国大陆手机号正则表达式
	// 支持格式：13812345678, +8613812345678, 138-1234-5678, 138 1234 5678
	phoneRegex := regexp.MustCompile(`^(\+86[-\s]?)?1[3-9]\d{9}$|^(\+86[-\s]?)?1[3-9]\d[-\s]?\d{4}[-\s]?\d{4}$`)

	// 清理格式字符
	cleanStr := strings.ReplaceAll(str, " ", "")
	cleanStr = strings.ReplaceAll(cleanStr, "-", "")

	return phoneRegex.MatchString(cleanStr)
}

// IsURL 验证URL格式
func IsURL(str string) bool {
	if str == "" {
		return false
	}

	// 使用Go标准库解析URL
	u, err := url.Parse(str)
	if err != nil {
		return false
	}

	// 检查是否有scheme和host
	return u.Scheme != "" && u.Host != ""
}

// IsIP 验证IP地址格式（支持IPv4和IPv6）
func IsIP(str string) bool {
	if str == "" {
		return false
	}

	// 使用Go标准库解析IP
	return net.ParseIP(str) != nil
}

// IsIPv4 验证IPv4地址格式
func IsIPv4(str string) bool {
	if str == "" {
		return false
	}

	ip := net.ParseIP(str)
	return ip != nil && ip.To4() != nil
}

// IsIPv6 验证IPv6地址格式
func IsIPv6(str string) bool {
	if str == "" {
		return false
	}

	ip := net.ParseIP(str)
	return ip != nil && ip.To4() == nil
}

// IsNumeric 验证是否为数字（整数或浮点数）
func IsNumeric(str string) bool {
	if str == "" {
		return false
	}

	// 数字正则表达式（支持整数、浮点数、负数、科学计数法）
	numericRegex := regexp.MustCompile(`^[-+]?(\d+\.?\d*|\.\d+)([eE][-+]?\d+)?$`)
	return numericRegex.MatchString(str)
}

// IsInteger 验证是否为整数
func IsInteger(str string) bool {
	if str == "" {
		return false
	}

	// 整数正则表达式
	integerRegex := regexp.MustCompile(`^[-+]?\d+$`)
	return integerRegex.MatchString(str)
}

// IsFloat 验证是否为浮点数
func IsFloat(str string) bool {
	if str == "" {
		return false
	}

	// 浮点数正则表达式
	floatRegex := regexp.MustCompile(`^[-+]?\d*\.\d+([eE][-+]?\d+)?$`)
	return floatRegex.MatchString(str)
}

// IsAlpha 验证是否只包含字母
func IsAlpha(str string) bool {
	if str == "" {
		return false
	}

	for _, r := range str {
		if !unicode.IsLetter(r) {
			return false
		}
	}
	return true
}

// IsAlphaNumeric 验证是否只包含字母和数字
func IsAlphaNumeric(str string) bool {
	if str == "" {
		return false
	}

	for _, r := range str {
		if !unicode.IsLetter(r) && !unicode.IsDigit(r) {
			return false
		}
	}
	return true
}

// ========== URL编码/解码函数 ==========

// UrlEncode URL编码（百分比编码）
func UrlEncode(str string) string {
	if str == "" {
		return ""
	}
	return url.QueryEscape(str)
}

// UrlDecode URL解码（百分比解码）
func UrlDecode(str string) (string, error) {
	if str == "" {
		return "", nil
	}
	return url.QueryUnescape(str)
}

// MustUrlDecode URL解码，解码失败返回原字符串
func MustUrlDecode(str string) string {
	if str == "" {
		return ""
	}
	decoded, err := url.QueryUnescape(str)
	if err != nil {
		return str
	}
	return decoded
}

// UrlPathEncode URL路径编码
func UrlPathEncode(str string) string {
	if str == "" {
		return ""
	}
	return url.PathEscape(str)
}

// UrlPathDecode URL路径解码
func UrlPathDecode(str string) (string, error) {
	if str == "" {
		return "", nil
	}
	return url.PathUnescape(str)
}

// MustUrlPathDecode URL路径解码，解码失败返回原字符串
func MustUrlPathDecode(str string) string {
	if str == "" {
		return ""
	}
	decoded, err := url.PathUnescape(str)
	if err != nil {
		return str
	}
	return decoded
}
